<?php

namespace common\models\user;

use Yii;
use common\helpers\IpHelper;
use common\helpers\ArrayHelper;
use yii\db\Exception;

/**
 * This is the model class for table "{{%user_connect}}".
 *
 * @property int $id
 * @property string $client 客户端
 * @property string $user_id 用户ID
 * @property string $openid 第三方帐号OPENID
 * @property string $unionid 第三方帐号UNIONID
 * @property string $created_at 创建时间
 * @property string $updated_at 更新时间
 */
class UserConnect extends \common\base\ActiveRecord {

    use \common\traits\Constants;
    use \common\traits\TimestampBehavior;
    use \common\traits\QueryInstanceActiveRecord;

    const CLIENT_MP = 'mp';
    const CLIENT_WECHAT = 'wechat';
    const CLIENT_WEIBO = 'weibo';
    const CLIENT_QQ = 'qq';

    /**
     * {@inheritdoc}
     */
    public static function tableName() {
        return '{{%user_connect}}';
    }

    /**
     * {@inheritdoc}
     */
    public function rules() {
        return [
            [['user_id', 'created_at', 'updated_at'], 'integer'],
            [['client'], 'string', 'max' => 32],
            [['openid', 'unionid'], 'string', 'max' => 255],
//            [['client', 'user_id'], 'unique', 'targetAttribute' => ['client', 'user_id']],
        ];
    }

    /**
     * {@inheritdoc}
     */
    public function attributeLabels() {
        return [
            'id' => 'ID',
            'client' => '客户端',
            'user_id' => '用户ID',
            'openid' => '第三方帐号OPENID',
            'unionid' => '第三方帐号unionid',
            'created_at' => '创建时间',
            'updated_at' => '更新时间',
        ];
    }

    public function getUser() {
        return $this->hasOne(Yii::$app->user->identity, ['id' => 'user_id']);
    }

    public function getMeta() {
        return $this->hasOne(UserMeta::className(), ['id' => 'user_id']);
    }

    public function getCacheToken() {
        return Yii::$app->cache->get('client_' . $this->id);
    }

    public function setCacheToken($data) {
        Yii::$app->cache->set('client_' . $this->id, $data);
    }

    public function autoRegister($mobile) {
        if ($this->user_id) {
            return $this->meta;
        }
        $clientMethod = 'authClient' . ucfirst($this->client);
        if (!method_exists($this, $clientMethod)) {
            return false;
        }
        $data = $this->getCacheToken();
        if ($data === false) {
            return false;
        }
        $userinfo = $this->$clientMethod($data);
        if ($userinfo === false) {
            return false;
        }

        $avatar = ArrayHelper::remove($userinfo, 'avatar');
        $location = ArrayHelper::remove($userinfo, 'location');
        $nickname = ArrayHelper::remove($userinfo, 'nickname');
        $gender = ArrayHelper::remove($userinfo, 'gender', 0);

        $user = new Yii::$app->user->identityClass;
        $user->setUsernameByOpenid($this->client, $this->openid);
        $user->generateAuthKey();

        $meta = new UserMeta();
        $meta->setAvatar($avatar);
        $user->setMobile($mobile);
        $meta->setUniqueNickname($nickname);

        $meta->ip = IpHelper::ip();
        $meta->location = $location;
        $meta->gender = (int) $gender;
        $meta->setMobile($mobile);

        $transaction = Yii::$app->db->beginTransaction();
        try {
            if (!$user->save()) {
                throw new Exception('账号信息创建失败');
            }
            $meta->id = $user->id;
            if (!$meta->save()) {
                throw new Exception('用户基本信息保存失败:' . $meta->errorMsg);
            }
            $this->user_id = $user->id;
            if (!$this->save()) {
                throw new Exception('用户基本信息保存失败');
            }
            $transaction->commit();
        } catch (Exception $e) {
            $transaction->rollBack();
            Yii::error($e->getMessage());
            return false;
        }

        return $this->meta;
    }

    public static function syncLogin($data) {
        $client = ArrayHelper::remove($data, 'client');
        $openid = ArrayHelper::remove($data, 'openid');
        $unionid = ArrayHelper::remove($data, 'unionid');
        $avatar = ArrayHelper::remove($data, 'avatar');
        $location = ArrayHelper::remove($data, 'location');
        $nickname = ArrayHelper::remove($data, 'nickname');
        $gender = ArrayHelper::remove($data, 'gender', 0);
        $mobile = ArrayHelper::remove($data, 'mobile');
        $connect = static::findOrNew([
            'client' => $client,
            'openid' => $openid,
            'unionid' => $unionid,
        ]);
        if (!$connect->user_id) {
            $user = new Yii::$app->user->identityClass;
            $user->setUsernameByOpenid($client, $openid);
            $user->generateAuthKey();

            $meta = new UserMeta();
            $meta->setAvatar($avatar);
            $meta->setUniqueNickname($nickname);

            $meta->ip = IpHelper::ip();
            $meta->location = $location;
            $meta->gender = $gender;

            if ($mobile) {
                $user->setMobile($mobile);
                $meta->setMobile($mobile);
            }
            $transaction = Yii::$app->db->beginTransaction();
            try {
                if (!$user->save()) {
                    throw new Exception('账号信息创建失败');
                }
                $meta->id = $user->id;
                if (!$meta->save()) {
                    throw new Exception('用户基本信息保存失败:' . $meta->errorMsg);
                }
                $connect->user_id = $user->id;
                if (!$connect->save()) {
                    throw new Exception('用户基本信息保存失败');
                }
                $transaction->commit();
            } catch (Exception $e) {
                $transaction->rollBack();
                return [
                    'status' => false,
                    'msg' => $e->getMessage()
                ];
            }
        } else {
            if (!$connect->save()) {
                return [
                    'status' => false,
                    'msg' => '关联信息保存失败:' . $connect->errorMsg
                ];
            }
        }
        return [
            'status' => true,
            'data' => $connect->meta
        ];
    }

    private function authClientWechat($data) {
        $openid = ArrayHelper::getValue($data, 'openid');
        $accessToken = ArrayHelper::getValue($data, 'access_token');
        if (!$openid || !$accessToken) {
            return false;
        }
        $wechat = Yii::$app->openWechat;
        $userinfo = $wechat->getSnsUserInfo($openid, $accessToken);
        if ($userinfo === false) {
            $refresh_token = ArrayHelper::getValue($data, 'refresh_token');
            $refreshData = $wechat->refreshOauth2AccessToken($refresh_token);
            //{
            //"access_token":"ACCESS_TOKEN",
            //"expires_in":7200,
            //"refresh_token":"REFRESH_TOKEN",
            //"openid":"OPENID",
            //"scope":"SCOPE"
            //}
            $accessToken = ArrayHelper::getValue($refreshData, 'access_token');
            $userinfo = $wechat->getSnsUserInfo($openid, $accessToken);
        }

        if ($userinfo === false) {
            return false;
        }
//                {
//                "openid":"OPENID",
//                "nickname":"NICKNAME",
//                "sex":1,
//                "province":"PROVINCE",
//                "city":"CITY",
//                "country":"COUNTRY",
//                "headimgurl": "http://wx.qlogo.cn/mmopen/g3MonUZtNHkdmzicIlibx6iaFqAc56vxLSUfpb6n5WKSYVY0ChQKkiaJSgQ1dZuTOgvLLrhJbERQQ4eMsv84eavHiaiceqxibJxCfHe/0",
//                "privilege":[
//                "PRIVILEGE1",
//                "PRIVILEGE2"
//                ],
//                "unionid": " o6_bmasdasdsad6_2sgVt7hMZOPfL"
//                }
        $avatar = ArrayHelper::getValue($userinfo, 'headimgurl');
        $location = ArrayHelper::getValue($userinfo, 'country') . ArrayHelper::getValue($userinfo, 'province') . ArrayHelper::getValue($userinfo, 'city');
        $gender = ArrayHelper::getValue($userinfo, 'sex');
        $nickname = ArrayHelper::getValue($userinfo, 'nickname');

        return compact('nickname', 'gender', 'avatar', 'location');
    }

    private function authClientQq($data) {
        $openid = ArrayHelper::getValue($data, 'openid');
        $accessToken = ArrayHelper::getValue($data, 'access_token');
        if (!$openid || !$accessToken) {
            return false;
        }
        $nickname = ArrayHelper::getValue($data, 'nickname');
        $gender = ArrayHelper::getValue($data, 'gender');
        $avatar = ArrayHelper::getValue($data, 'avatar');

        return compact('nickname', 'gender', 'avatar');
    }

}
